import * as THREE from 'three';
const model = new THREE.Group();
// var areaS = 0.03;//把飞线相关柱子、光圈、棱锥全部缩放areaS倍
var size = 1.2
const lineGroup = new THREE.Group();//边界线组
const meshGroup = new THREE.Group();//区域填充组
const pillarMeshGroup = new THREE.Group();//柱子组
const cityPointGroup = new THREE.Group();//城市热点组
const coneMeshGroup = new THREE.Group();//棱锥组
// const size = 1.2;
const mapHeight = 1
const loader = new THREE.FileLoader();
loader.setResponseType("json")
const gdpData = {}
// 解析gdp文件数据
loader.load('/gdp.json',(data)=>{ 
    data.arr.forEach((elem)=>{
        gdpData[elem.name] = elem.value
    })

})
loader.load('/china2.json',(data)=>{
    data.features.forEach((area)=>{
        // coordinates数据分为单组和多组，将单组的封装为多组
        if(area.geometry.type === 'Polygon'){
            area.geometry.coordinates = [area.geometry.coordinates]
        }
        lineGroup.add(moreLine(area.geometry.coordinates,mapHeight)) 
        meshGroup.add(shapeMesh(area.geometry.coordinates,area.properties.name,area.properties.center,gdpData[area.properties.name]))
        pillarMeshGroup.add(prismMesh(area.properties.name,area.properties.center,gdpData[area.properties.name]))
        cityPointGroup.add(cityPointMesh(area.properties.center,area.properties.name))
        if(area.properties.name === "河南省"){
            // coneMeshGroup.add(coneMesh(area.properties.name,area.properties.center))
        }

    })
    // const pathLine = curveLine()
    model.add(lineGroup,meshGroup,pillarMeshGroup,cityPointGroup,coneMeshGroup)
})

// 批量产生轮廓线
const moreLine = (coordinates,gdpvalue)=>{
    const groupLine = new THREE.Group();
    coordinates.forEach(polygon => {
        var pointArr = []
        polygon[0].forEach((elem)=>{
            pointArr.push(elem[0],elem[1],0)
        })
        groupLine.add(oneLine(pointArr))
    });
    groupLine.position.z += gdpvalue+ 0.001*gdpvalue
    return groupLine
}
// 产生一条轮廓线
const oneLine = (pointArr)=>{
    const geometry = new THREE.BufferGeometry();
    const vertices = new Float32Array(pointArr);
    geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
    const material = new THREE.LineBasicMaterial({
        color: 0x006666
    });
    const line = new THREE.LineLoop(geometry,material);
    return line;
}
// 产生多边形面
const shapeMesh = (coordinates,name,lngLat,GDP)=>{
    var heartShape = [];//轮廓形状Shape集合
    coordinates.forEach(polygon => {
        var pointArr = []
        polygon[0].forEach((elem)=>{
            pointArr.push(new THREE.Vector3(elem[0],elem[1],0))
        })
        const shape = new THREE.Shape(pointArr);
        heartShape.push(shape)
    });
    var material = new THREE.MeshLambertMaterial({
        color: 0x004444,
        // side: THREE.DoubleSide, //两面可见
    }); //材质对象
    var geometry = new THREE.ExtrudeGeometry( heartShape ,{
        depth: mapHeight, //拉伸长度
        bevelEnabled: false //无倒角
    });
    var mesh =  new THREE.Mesh( geometry, material )
    mesh.lngLat = lngLat
    mesh.name = name
    mesh.GDP = GDP
    return mesh
}
// 根据GDP产生棱柱
const prismMesh = (name,lngLat,value)=>{
    if(!name){
        return
    }
    const maxGDP = 100000
    var color1 = new THREE.Color(0x00ffff);
    var color2 = new THREE.Color(0x00ff33);
    var maxH = 4; // 假设最大值
    const heightValue =  1 + (maxH - 1) * Math.random();
    const geometry = new THREE.CylinderGeometry( 0.3, 0.3, heightValue, 6 );
    const material = new THREE.MeshLambertMaterial( {color: color1.clone().lerp(color2,value/maxGDP)} );
    geometry.computeVertexNormals()
    const cylinder = new THREE.Mesh( geometry, material );
    cylinder.position.set(lngLat[0],lngLat[1],mapHeight)
    cylinder.position.z += heightValue/2
    cylinder.rotation.x = Math.PI/2
    cylinder.name = name + "棱柱"
    return cylinder
}
// 产生光圈的几何体
const cityPointGeometry = new THREE.PlaneGeometry( size, size );
// 产生动态光圈
const cityPointMesh = (lngLat,name)=>{
    if(!lngLat){
        return
    }
    const texture = new THREE.TextureLoader().load( '/端点标注.png' );
    const material = new THREE.MeshBasicMaterial( {
        map:texture,
        color: 0x00ffff,//设置光圈颜色
        transparent: true,
        side: THREE.DoubleSide,
        depthWrite: false, //是否对深度缓冲区有任何的影响
    } );
    const plane = new THREE.Mesh( cityPointGeometry, material );
    plane._s = Math.random()*1.8 + 0.7//光圈的初始大小在0.7-2.5之间
    plane.position.set(lngLat[0],lngLat[1],mapHeight + Math.random() )
    plane.name = name + "光圈"
    return plane
}
// 产生一个棱锥
const coneMesh = (name,lngLat)=>{
    if(!name){
        return
    }
    const geometry = new THREE.ConeGeometry( 0.5, 2, 4 );
    const material = new THREE.MeshLambertMaterial( {color: 0x00ffff} );
    const cone = new THREE.Mesh( geometry, material );
    cone.position.set(lngLat[0],lngLat[1],mapHeight + 1.01)
    cone.rotateX(-Math.PI/2) 
    function render3 (){
        cone.rotateY(Math.PI/180)
        requestAnimationFrame(render3);
    }
    render3()
    return cone
}
function render2 (){
    // 动态光圈
    cityPointGroup.children.forEach((obj)=>{
        obj._s += 0.01
        obj.scale.set(obj._s,obj._s,1)
        // _s的值在0.7-1时，透明度在0-1之间变化，3-5时透明度在1-0之间变化
        if(obj._s < 1){
            obj.material.opacity = (obj._s - 0.7) * 3.333;
        }else if(obj._s<2.5 && obj._s >= 1){
            obj.material.opacity = 1 - (obj._s - 1) / 1.5;
        }else if(obj._s >= 2.5){
            obj._s = 0.7
        }
    })
    requestAnimationFrame(render2);
}
render2()
// 产生一条曲线轨迹
const curveLine = (targetProvince,everyProvince,currentIndex) =>{
    const centerX = (everyProvince[0] + targetProvince[0])/2
    const centerY = (everyProvince[1] + targetProvince[1])/2
    // 计算二维两个点的长度
    const A = new THREE.Vector2(targetProvince[0], targetProvince[1]);
    const B = new THREE.Vector2(everyProvince[0], everyProvince[1]);
    const AB = new THREE.Vector2();
    // 两点的距离
    AB.subVectors(B,A);
    const arr = [
        new THREE.Vector3(targetProvince[0], targetProvince[1], mapHeight + 0.1),
        new THREE.Vector3(centerX, centerY, AB.length()/5),
        new THREE.Vector3(everyProvince[0], everyProvince[1], mapHeight + 0.1)
    ]
    // 三维样条曲线
    const curve = new THREE.CatmullRomCurve3(arr);
    //曲线上获取点
    const pointsArr = curve.getPoints(100); 
    const geometry = new THREE.BufferGeometry();
    //读取坐标数据赋值给几何体顶点
    geometry.setFromPoints(pointsArr); 
    // 线材质
    const material = new THREE.LineBasicMaterial({
    color: 0x006666
    });
    // 线模型
    const line = new THREE.Line(geometry, material);
    // 从轨迹线上去10个点，从第20个开始取，生成一个飞线段
    var index = Number(currentIndex)
    var num = 10
    var flyLineArr = pointsArr.slice(index,index+num)
    const geometry2 = new THREE.BufferGeometry();
    // 将20个点形成一个新的曲线，在上面取更多的点
    const curve2 = new THREE.CatmullRomCurve3(flyLineArr);
    //曲线上获取点
    const pointsArr2 = curve2.getPoints(100); 
    // 将100个点设置给geometry2
    geometry2.setFromPoints(pointsArr2);
    
    const colorArr = []
    for(let i = 0;i < pointsArr2.length;i++){
        var color1 = new THREE.Color(0x006666); //轨迹线颜色 青色
        var color2 = new THREE.Color(0xffff00); //黄色
        var color = color1.lerp(color2, i / pointsArr2.length)
        colorArr.push(color.r, color.g, color.b);
    }
    // 设置几何体顶点颜色数据
    geometry2.attributes.color = new THREE.BufferAttribute(new Float32Array(colorArr), 3);
    const material2 = new THREE.PointsMaterial({
        // color: 0xffffff,
        vertexColors: true,
        size: 5.0, //点大小
        });
        // 修改点材质的着色器源码(注意：不同版本细节可能会稍微会有区别，不过整体思路是一样的)
    // 每个顶点对应一个百分比数据attributes.percent 用于控制点的渲染大小
    var percentArr = []; //attributes.percent的数据
    for (var i = 0; i < pointsArr2.length; i++) {
        percentArr.push(i / pointsArr2.length);
    }
    var percentAttribue = new THREE.BufferAttribute(new Float32Array(percentArr), 1);
    geometry2.attributes.percent = percentAttribue;
    material2.onBeforeCompile = function (shader) {
        // 顶点着色器中声明一个attribute变量:百分比
        shader.vertexShader = shader.vertexShader.replace(
            'void main() {',
            [
                'attribute float percent;', //顶点大小百分比变量，控制点渲染大小
                'void main() {',
            ].join('\n') // .join()把数组元素合成字符串
        );
        // 调整点渲染大小计算方式
        shader.vertexShader = shader.vertexShader.replace(
            'gl_PointSize = size;',
            [
                'gl_PointSize = percent * size;',
            ].join('\n') // .join()把数组元素合成字符串
        );
    };
    // 飞线
    function render (){
        if(index+num >= pointsArr.length){
            index = 0
        }
        index++
        const points2 = pointsArr.slice(index,index+num)
        var curve3 = new THREE.CatmullRomCurve3(points2);
        var newPoints2 = curve3.getPoints(100); //获取更多的点数
        geometry2.setFromPoints(newPoints2);
        requestAnimationFrame(render);
    }
    render()
    // 线模型
    const flyLine = new THREE.Points(geometry2, material2);
    return [line,flyLine]
}
/*释放模型对象几何体和材质所占用的内存*/
function disposeGroup(group) {
    // .traverse方法递归遍历group的所有后代
    group.traverse(function(obj) {
      if (obj.type == 'Mesh' || obj.type == 'Line') {
        obj.geometry.dispose();
        obj.material.dispose();
      }
    })
    if (group.children.length) {
      group.children = []; //删除所有后代模型对象
    }
  }

export {model,meshGroup,pillarMeshGroup,coneMesh,curveLine,disposeGroup};